#include <windows.h>
#include <windowsx.h> 

/*鼠标位置结构*/
POINT MousePos;

/*地图中的颜色RGB变量声明*/
const COLORREF NormalRoadColor = RGB(0,250,0);
const COLORREF EndZoneColor = RGB(46,139,87);
const COLORREF StartZoneColor = RGB(178,34,34);
const COLORREF PlayCheckColor = RGB(0,139,69);
const COLORREF BackGroundColor = RGB(8,236,239);

enum _PointState{Normal = 1,Out = 0,Win = -1,Pass = 2} PointState;    //游戏开始用于标记点的状态:(1:正常.0:走出地图外.-1:胜利.2:通过本关).
bool IsPlay = false;    //是否开始了游戏. 
bool IsFirst = true;    //是否第一次开始判断鼠标位置. 
unsigned int CheckPointsNum = 1;

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void Init(HWND,int,int);
bool Start(HDC&,int,int);
void DrawNote(HDC&,int,int); 
void FirstPass(HDC&,int,int,HBRUSH,bool);
void SecondPass(HDC&,int,int,HBRUSH,bool);
void ThirdPass(HDC&,int,int,HBRUSH,bool);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;
	HWND hwnd; 
	MSG msg;

	memset(&wc,0,sizeof(wc));
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	

	wc.hbrBackground = CreateSolidBrush(BackGroundColor);
	wc.lpszClassName = "Scary_Map";
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 

	if(!RegisterClassEx(&wc))
	{
		MessageBox(NULL,TEXT("窗口类注册失败!"),TEXT("错误!"),MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(NULL,"Scary_Map",TEXT("吓人迷宫"),WS_VISIBLE|WS_OVERLAPPEDWINDOW^WS_SIZEBOX^WS_MAXIMIZEBOX,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		720, /* width */
		720, /* height */
		NULL,NULL,hInstance,NULL);
		
	ShowWindow(hwnd,nCmdShow);
	UpdateWindow(hwnd);
	
	if(hwnd == NULL)
	{
		MessageBox(NULL, TEXT("窗口创建失败!"),TEXT("错误!"),MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	while(GetMessage(&msg, NULL, 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg); 
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	static int cxClient;
	static int cyClient;
	HDC hdc;
	PAINTSTRUCT ps;
	HBRUSH hBrush;
	HFONT hFont; 
	switch(Message)
	{
		case WM_SIZE:
		case WM_CREATE:
		{
			cxClient = GET_X_LPARAM(lParam);
			cyClient = GET_Y_LPARAM(lParam);
			PointState = Normal;
			break;
		}
		case WM_PAINT:
		{
			hdc = BeginPaint(hwnd,&ps);
			/*只有IsPlay设置为True才能绘制*/
			if(IsPlay)
			{
				SetBkMode(hdc,TRANSPARENT);
				hBrush = CreateSolidBrush(NormalRoadColor);
				SelectObject(hdc,hBrush);
				
				hFont=CreateFont(20,10,0,0,FW_THIN,false,false,false,
				GB2312_CHARSET,OUT_CHARACTER_PRECIS,
				CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
				FF_MODERN,TEXT("宋体"));
				SelectObject(hdc,hFont);
				
				switch(CheckPointsNum)
				{
					case 1:FirstPass(hdc,cxClient,cyClient,hBrush,true);break;
					case 2:SecondPass(hdc,cxClient,cyClient,hBrush,true);break;
					case 3:ThirdPass(hdc,cxClient,cyClient,hBrush,true);break;
					default:break;
				}
			}
			else
			{	
				/*绘制开始界面*/
				hFont=CreateFont(20,10,0,0,FW_THIN,false,false,false,
				GB2312_CHARSET,OUT_CHARACTER_PRECIS,
				CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
				FF_MODERN,TEXT("宋体"));
				SelectObject(hdc,hFont);
				Start(hdc,cxClient,cyClient);
			}
			break;
		}
		
		case WM_MOUSEMOVE:
		{
			hdc = GetDC(hwnd);
			MousePos.x = GET_X_LPARAM(lParam);
			MousePos.y = GET_Y_LPARAM(lParam);
			
			if(IsPlay)
			{
				switch(CheckPointsNum)
				{
					case 1:FirstPass(hdc,cxClient,cyClient,hBrush,false);break;
					case 2:SecondPass(hdc,cxClient,cyClient,hBrush,false);break;
					case 3:ThirdPass(hdc,cxClient,cyClient,hBrush,false);break;
					default:break;
				}
			}
			ReleaseDC(hwnd,hdc);
			break;
		}
		
		case WM_LBUTTONUP:
		{
			hdc = GetDC(hwnd);
			if(GetPixel(hdc,GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)) == PlayCheckColor)
			{
				IsPlay = true;
				Init(hwnd,cxClient,cyClient);
				InvalidateRect(hwnd,NULL,true);
			}
			ReleaseDC(hwnd,hdc);
			break;
		}

		case WM_DESTROY:
		{
			DeleteObject(hBrush);
			DeleteObject(hFont);
			PostQuitMessage(0);
			break;
		}
		default:
		{
			return DefWindowProc(hwnd,Message,wParam,lParam);
		}
	}
	if(PointState == Win)
	{
		MessageBox(hwnd,TEXT("假装有吓人的图片.jpg"),TEXT("吓一跳!"),MB_ICONEXCLAMATION | MB_OK);
		DestroyWindow(hwnd);
	}
	else if(!PointState)
	{
		MessageBox(hwnd,TEXT("游戏失败，走出去了."),TEXT("提示"),MB_ICONEXCLAMATION | MB_OK);
		PointState = Normal;
		IsPlay = false;
		CheckPointsNum = 1;	//重设关卡数 
		InvalidateRect(hwnd,NULL,true);
	}
	else if(PointState == Pass)
	{
		PointState = Normal;
		CheckPointsNum++;
		IsFirst = true;
		Init(hwnd,cxClient,cyClient);
		InvalidateRect(hwnd,NULL,true);
	}
	return 0;
}

/**
*初始化一些相关的值,设置鼠标位置.
*@param hwnd:窗口句柄.
*@param cxClient:客户区宽度.
*@param cyClient:客户区高度.
*Return:None.
*/
void Init(HWND hwnd,int cxClient,int cyClient)
{
	PointState = Normal;
	switch(CheckPointsNum)
	{
		case 1:
		{
			MousePos.x = cxClient/32*8 + 10;
			MousePos.y = cyClient/32*8 + 10;
			break;
		}
		case 2:
		{
			MousePos.x = cxClient/32*8 + 10;
			MousePos.y = cyClient/32*8 + 10;
			break;
		}
		case 3:
		{
			MousePos.x = cxClient/32*8 + 10;
			MousePos.y = cyClient/32*15 + 10;
			break;
		}
	}
	ClientToScreen(hwnd,&MousePos);
	SetCursorPos(MousePos.x,MousePos.y);
}

/**
*在客户区画出区域注释.
*@param hdc:Context句柄.
*@param width:客户区宽度.
*@param height:客户区高度. 
*Return:None.
*/
void DrawNote(HDC& hdc,int width,int height)
{
	RECT Start;
	RECT End;
	Start.left = width/32*8;
	Start.top = height/32*21 + 20;
	Start.right = width/32*10;
	Start.bottom = width/32*22 + 20;
	
	End.left = width/32*8;
	End.top = height/32*24 + 20;
	End.right = width/32*10;
	End.bottom = width/32*25 + 20;
	
	FillRect(hdc,&Start,CreateSolidBrush(StartZoneColor));
	FillRect(hdc,&End,CreateSolidBrush(EndZoneColor));
	TextOut(hdc,width/32*11,height/32*22 + 10,TEXT("开始区域.(鼠标从这里出发)"),lstrlen(TEXT("开始区域.(鼠标从这里出发)")));
	TextOut(hdc,width/32*11,height/32*25 + 10,TEXT("终点区域.(鼠标到这里结束)"),lstrlen(TEXT("终点区域.(鼠标到这里结束)")));
}

/**
*第一关地图绘制以及检测鼠标位置.
*@param hdc:Context句柄，用于填充矩形.
*@param width:客户区宽度.
*@param height:客户区高度.
*@param IsReDraw:标志位，决定该函数的不同作用.TRUE:绘制地图.FALSE:检测鼠标位置.
*Return:None.
*/
void FirstPass(HDC &hdc,int width,int height,HBRUSH Brush,bool IsReDraw)
{
	/*绘制第一关地图部分-开始*/
	RECT Startrect;
	Startrect.left = width/32*8;
	Startrect.top = height/32*8;
	Startrect.right = width/32*10;
	Startrect.bottom = height/32*10;
	
	RECT Roadrect[5];
	Roadrect[0].left = width/32*10;
	Roadrect[0].top = height/32*8;
	Roadrect[0].right = width/32*12;
	Roadrect[0].bottom = height/32*18;
	
	Roadrect[1].left = width/32*12;
	Roadrect[1].top = height/32*16;
	Roadrect[1].right = width/32*22;
	Roadrect[1].bottom = height/32*18;
	
	Roadrect[2].left = width/32*20;
	Roadrect[2].top = height/32*12;
	Roadrect[2].right = width/32*22;
	Roadrect[2].bottom = height/32*16;
	
	Roadrect[3].left = width/32*16;
	Roadrect[3].top = height/32*12;
	Roadrect[3].right = width/32*20;
	Roadrect[3].bottom = height/32*14;
	
	Roadrect[4].left = width/32*16;
	Roadrect[4].top = height/32*8;
	Roadrect[4].right = width/32*18;
	Roadrect[4].bottom = height/32*12;
	
	RECT Endrect;
	
	Endrect.left = width/32*18;
	Endrect.top = height/32*8;
	Endrect.right = width/32*20;
	Endrect.bottom = height/32*10;
	
	if(IsReDraw)
	{
		TextOut(hdc,width/2-25,height/32*20,TEXT("第一关"),lstrlen(TEXT("第一关")));
		DrawNote(hdc,width,height);
		FillRect(hdc,&Startrect,CreateSolidBrush(StartZoneColor));
		FillRect(hdc,&Roadrect[0],Brush);
		FillRect(hdc,&Roadrect[1],Brush);
		FillRect(hdc,&Roadrect[2],Brush);
		FillRect(hdc,&Roadrect[3],Brush);
		FillRect(hdc,&Roadrect[4],Brush);
		FillRect(hdc,&Endrect,CreateSolidBrush(EndZoneColor));
	}
	/*绘制第一关地图部分-结束*/
	
	/*检测鼠标位置-开始*/
	if(!IsReDraw)
	{
		if(IsFirst)
		{
			
			/*当时IsPlay设置为True时的第一次检测,直接将PointState设置为1*/
			PointState = Normal;
			IsFirst = false;
			return;
		}
		//通过提取某个点的颜色值检测鼠标的位置,进而对PointState进行设置. 
		if(GetPixel(hdc,MousePos.x,MousePos.y) == StartZoneColor) 
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == EndZoneColor)
		{
			PointState = Pass;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == NormalRoadColor)
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == BackGroundColor)
		{ 
			PointState = Out;
			return;
		}
	}
	/*检测鼠标位置-结束*/
	return;
}

/**
*第二关地图绘制以及检测鼠标位置.
*@param hdc:Context句柄，用于填充矩形.
*@param width:客户区宽度.
*@param height:客户区高度.
*@param IsReDraw:标志位，决定该函数的不同作用.TRUE:绘制地图.FALSE:检测鼠标位置.
*Return:None.
*/
void SecondPass(HDC &hdc,int width,int height,HBRUSH Brush,bool IsReDraw)
{
	RECT Startrect;
	Startrect.left = width/32*8;
	Startrect.top = height/32*8;
	Startrect.right = width/32*10;
	Startrect.bottom = height/32*10;
	
	RECT Roadrect[9];
	Roadrect[0].left = width/32*10;
	Roadrect[0].top = height/32*8;
	Roadrect[0].right = width/32*11;
	Roadrect[0].bottom = height/32*12;
	
	Roadrect[1].left = width/32*11;
	Roadrect[1].top = height/32*10;
	Roadrect[1].right = width/32*12;
	Roadrect[1].bottom = height/32*14;  
	
	Roadrect[2].left = width/32*12;
	Roadrect[2].top = height/32*12;
	Roadrect[2].right = width/32*17;
	Roadrect[2].bottom = height/32*14;
	
	Roadrect[3].left = width/32*15;
	Roadrect[3].top = height/32*5;
	Roadrect[3].right = width/32*17;
	Roadrect[3].bottom = height/32*12;
	
	Roadrect[4].left = width/32*17;
	Roadrect[4].top = height/32*5;
	Roadrect[4].right = width/32*20;
	Roadrect[4].bottom = height/32*6;
	
	Roadrect[5].left = width/32*19;
	Roadrect[5].top = height/32*6;
	Roadrect[5].right = width/32*20;
	Roadrect[5].bottom = height/32*9;
	
	Roadrect[6].left = width/32*20;
	Roadrect[6].top = height/32*8;
	Roadrect[6].right = width/32*23;
	Roadrect[6].bottom = height/32*9;
	
	Roadrect[7].left = width/32*21;
	Roadrect[7].top = height/32*9;
	Roadrect[7].right = width/32*23;
	Roadrect[7].bottom = height/32*11;
	
	Roadrect[8].left = width/32*22;
	Roadrect[8].top = height/32*11;
	Roadrect[8].right = width/32*24;
	Roadrect[8].bottom = height/32*13;
	
	RECT Endrect;
	
	Endrect.left = width/32*22;
	Endrect.top = height/32*13;
	Endrect.right = width/32*24;
	Endrect.bottom = height/32*15;
	
	if(IsReDraw)
	{
		TextOut(hdc,width/2-25,height/32*20,TEXT("第二关"),lstrlen(TEXT("第二关")));
		DrawNote(hdc,width,height);
		FillRect(hdc,&Startrect,CreateSolidBrush(StartZoneColor));
		FillRect(hdc,&Roadrect[0],Brush);
		FillRect(hdc,&Roadrect[1],Brush);
		FillRect(hdc,&Roadrect[2],Brush);
		FillRect(hdc,&Roadrect[3],Brush);
		FillRect(hdc,&Roadrect[4],Brush);
		FillRect(hdc,&Roadrect[5],Brush);
		FillRect(hdc,&Roadrect[6],Brush);
		FillRect(hdc,&Roadrect[7],Brush);
		FillRect(hdc,&Roadrect[8],Brush);
		FillRect(hdc,&Endrect,CreateSolidBrush(EndZoneColor));
	}
	
	/*检测鼠标位置-开始*/
	if(!IsReDraw)
	{
		if(IsFirst)
		{
			/*当时IsPlay设置为True时的第一次检测,直接将PointState设置为1*/
			PointState = Normal;
			IsFirst = false;
			return;
		}
		//通过提取某个点的颜色值检测鼠标的位置,进而对PointState进行设置. 
		if(GetPixel(hdc,MousePos.x,MousePos.y) == StartZoneColor) 
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == EndZoneColor)
		{
			PointState = Pass;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == NormalRoadColor)
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == BackGroundColor)
		{ 
			PointState = Out;
			return;
		}
	}
	/*检测鼠标位置-结束*/
	return;
}

/**
*第三关地图绘制以及检测鼠标位置.
*@param hdc:Context句柄，用于填充矩形.
*@param width:客户区宽度.
*@param height:客户区高度.
*@param IsReDraw:标志位，决定该函数的不同作用.TRUE:绘制地图.FALSE:检测鼠标位置.
*Return:None.
*/
void ThirdPass(HDC &hdc,int width,int height,HBRUSH Brush,bool IsReDraw)
{
	RECT Startrect;
	Startrect.left = width/32*8;
	Startrect.top = height/32*15;
	Startrect.right = width/32*10;
	Startrect.bottom = height/32*17;
	
	RECT Roadrect[7];
	Roadrect[0].left = width/32*8;
	Roadrect[0].top = height/32*13;
	Roadrect[0].right = width/32*21;
	Roadrect[0].bottom = height/32*15;
	
	Roadrect[1].left = width/32*21;
	Roadrect[1].top = height/32*9;
	Roadrect[1].right = width/32*23;
	Roadrect[1].bottom = height/32*15;
	
	Roadrect[2].left = width/32*8;
	Roadrect[2].top = height/32*9;
	Roadrect[2].right = width/32*21;
	Roadrect[2].bottom = height/32*11;
	
	Roadrect[3].left = width/32*8;
	Roadrect[3].top = height/32*5;
	Roadrect[3].right = width/32*10;
	Roadrect[3].bottom = height/32*9;
	
	Roadrect[4].left = width/32*10;
	Roadrect[4].top = height/32*5;
	Roadrect[4].right = width/32*15;
	Roadrect[4].bottom = height/32*6;
	
	Roadrect[5].left = width/32*14;
	Roadrect[5].top = height/32*6;
	Roadrect[5].right = width/32*20;
	Roadrect[5].bottom = height/32*7 - 10;	//加窄路段. 
	
	Roadrect[6].left = width/32*19;
	Roadrect[6].top = height/32*5 + 12;    //加窄路段.
	Roadrect[6].right = width/32*25;
	Roadrect[6].bottom = height/32*6;
	
	RECT Endrect;
	
	Endrect.left = width/32*24;
	Endrect.top = height/32*6;
	Endrect.right = width/32*25;
	Endrect.bottom = height/32*8;
	
	if(IsReDraw)
	{
		TextOut(hdc,width/2-25,height/32*20,TEXT("第三关"),lstrlen(TEXT("第三关")));
		DrawNote(hdc,width,height);
		FillRect(hdc,&Startrect,CreateSolidBrush(StartZoneColor));
		FillRect(hdc,&Roadrect[0],Brush);
		FillRect(hdc,&Roadrect[1],Brush);
		FillRect(hdc,&Roadrect[2],Brush);
		FillRect(hdc,&Roadrect[3],Brush);
		FillRect(hdc,&Roadrect[4],Brush);
		FillRect(hdc,&Roadrect[5],Brush);
		FillRect(hdc,&Roadrect[6],Brush);
		FillRect(hdc,&Endrect,CreateSolidBrush(EndZoneColor));
	}
	
	/*检测鼠标位置-开始*/
	if(!IsReDraw)
	{
		if(IsFirst)
		{
			/*当时IsPlay设置为True时的第一次检测,直接将PointState设置为1*/
			PointState = Normal;
			IsFirst = false;
			return;
		}
		//通过提取某个点的颜色值检测鼠标的位置,进而对PointState进行设置. 
		if(GetPixel(hdc,MousePos.x,MousePos.y) == StartZoneColor) 
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == EndZoneColor)
		{
			PointState = Win;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == NormalRoadColor)
		{
			PointState = Normal;
			return; 
		}
		else if(GetPixel(hdc,MousePos.x,MousePos.y) == BackGroundColor)
		{ 
			PointState = Out;
			return;
		}
	}
	/*检测鼠标位置-结束*/
	return;
}

/**
*绘制开始界面.
*@param hdc:Context句柄.
*@param width:客户区宽度.
*@param height:客户区高度. 
*Return:None.
*/
bool Start(HDC& hdc,int width,int height)
{
	RECT rect;
	SetBkMode(hdc,TRANSPARENT);
	rect.left = width/32*9;
	rect.top = height/32*7;
	rect.right = width/32*22;
	rect.bottom = height/32*12;
	FillRect(hdc,&rect,CreateSolidBrush(PlayCheckColor));
	TextOut(hdc,width/32*10,height/32*15,TEXT("请点击上面的矩形进行游戏."),lstrlen(TEXT("请点击上面的矩形进行游戏.")));
	IsFirst = true;
}
